1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package scouter.javassist;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileNotFoundException;
22 import java.io.FilenameFilter;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.net.MalformedURLException;
27 import java.net.URL;
28 import java.util.jar.JarEntry;
29 import java.util.jar.JarFile;
30
31 import scouter.javassist.CannotCompileException;
32 import scouter.javassist.ClassClassPath;
33 import scouter.javassist.ClassPath;
34 import scouter.javassist.NotFoundException;
35
36
37 final class ClassPathList {
38 ClassPathList next;
39 ClassPath path;
40
41 ClassPathList(ClassPath p, ClassPathList n) {
42 next = n;
43 path = p;
44 }
45 }
46
47 final class DirClassPath implements ClassPath {
48 String directory;
49
50 DirClassPath(String dirName) {
51 directory = dirName;
52 }
53
54 public InputStream openClassfile(String classname) {
55 try {
56 char sep = File.separatorChar;
57 String filename = directory + sep
58 + classname.replace('.', sep) + ".class";
59 return new FileInputStream(filename.toString());
60 }
61 catch (FileNotFoundException e) {}
62 catch (SecurityException e) {}
63 return null;
64 }
65
66 public URL find(String classname) {
67 char sep = File.separatorChar;
68 String filename = directory + sep
69 + classname.replace('.', sep) + ".class";
70 File f = new File(filename);
71 if (f.exists())
72 try {
73 return f.getCanonicalFile().toURI().toURL();
74 }
75 catch (MalformedURLException e) {}
76 catch (IOException e) {}
77
78 return null;
79 }
80
81 public void close() {}
82
83 public String toString() {
84 return directory;
85 }
86 }
87
88 final class JarDirClassPath implements ClassPath {
89 JarClassPath[] jars;
90
91 JarDirClassPath(String dirName) throws NotFoundException {
92 File[] files = new File(dirName).listFiles(new FilenameFilter() {
93 public boolean accept(File dir, String name) {
94 name = name.toLowerCase();
95 return name.endsWith(".jar") || name.endsWith(".zip");
96 }
97 });
98
99 if (files != null) {
100 jars = new JarClassPath[files.length];
101 for (int i = 0; i < files.length; i++)
102 jars[i] = new JarClassPath(files[i].getPath());
103 }
104 }
105
106 public InputStream openClassfile(String classname) throws NotFoundException {
107 if (jars != null)
108 for (int i = 0; i < jars.length; i++) {
109 InputStream is = jars[i].openClassfile(classname);
110 if (is != null)
111 return is;
112 }
113
114 return null;
115 }
116
117 public URL find(String classname) {
118 if (jars != null)
119 for (int i = 0; i < jars.length; i++) {
120 URL url = jars[i].find(classname);
121 if (url != null)
122 return url;
123 }
124
125 return null;
126 }
127
128 public void close() {
129 if (jars != null)
130 for (int i = 0; i < jars.length; i++)
131 jars[i].close();
132 }
133 }
134
135 final class JarClassPath implements ClassPath {
136 JarFile jarfile;
137 String jarfileURL;
138
139 JarClassPath(String pathname) throws NotFoundException {
140 try {
141 jarfile = new JarFile(pathname);
142 jarfileURL = new File(pathname).getCanonicalFile()
143 .toURI().toURL().toString();
144 return;
145 }
146 catch (IOException e) {}
147 throw new NotFoundException(pathname);
148 }
149
150 public InputStream openClassfile(String classname)
151 throws NotFoundException
152 {
153 try {
154 String jarname = classname.replace('.', '/') + ".class";
155 JarEntry je = jarfile.getJarEntry(jarname);
156 if (je != null)
157 return jarfile.getInputStream(je);
158 else
159 return null;
160 }
161 catch (IOException e) {}
162 throw new NotFoundException("broken jar file?: "
163 + jarfile.getName());
164 }
165
166 public URL find(String classname) {
167 String jarname = classname.replace('.', '/') + ".class";
168 JarEntry je = jarfile.getJarEntry(jarname);
169 if (je != null)
170 try {
171 return new URL("jar:" + jarfileURL + "!/" + jarname);
172 }
173 catch (MalformedURLException e) {}
174
175 return null;
176 }
177
178 public void close() {
179 try {
180 jarfile.close();
181 jarfile = null;
182 }
183 catch (IOException e) {}
184 }
185
186 public String toString() {
187 return jarfile == null ? "<null>" : jarfile.toString();
188 }
189 }
190
191 final class ClassPoolTail {
192 protected ClassPathList pathList;
193
194 public ClassPoolTail() {
195 pathList = null;
196 }
197
198 public String toString() {
199 StringBuffer buf = new StringBuffer();
200 buf.append("[class path: ");
201 ClassPathList list = pathList;
202 while (list != null) {
203 buf.append(list.path.toString());
204 buf.append(File.pathSeparatorChar);
205 list = list.next;
206 }
207
208 buf.append(']');
209 return buf.toString();
210 }
211
212 public synchronized ClassPath insertClassPath(ClassPath cp) {
213 pathList = new ClassPathList(cp, pathList);
214 return cp;
215 }
216
217 public synchronized ClassPath appendClassPath(ClassPath cp) {
218 ClassPathList tail = new ClassPathList(cp, null);
219 ClassPathList list = pathList;
220 if (list == null)
221 pathList = tail;
222 else {
223 while (list.next != null)
224 list = list.next;
225
226 list.next = tail;
227 }
228
229 return cp;
230 }
231
232 public synchronized void removeClassPath(ClassPath cp) {
233 ClassPathList list = pathList;
234 if (list != null)
235 if (list.path == cp)
236 pathList = list.next;
237 else {
238 while (list.next != null)
239 if (list.next.path == cp)
240 list.next = list.next.next;
241 else
242 list = list.next;
243 }
244
245 cp.close();
246 }
247
248 public ClassPath appendSystemPath() {
249 return appendClassPath(new ClassClassPath());
250 }
251
252 public ClassPath insertClassPath(String pathname)
253 throws NotFoundException
254 {
255 return insertClassPath(makePathObject(pathname));
256 }
257
258 public ClassPath appendClassPath(String pathname)
259 throws NotFoundException
260 {
261 return appendClassPath(makePathObject(pathname));
262 }
263
264 private static ClassPath makePathObject(String pathname)
265 throws NotFoundException
266 {
267 String lower = pathname.toLowerCase();
268 if (lower.endsWith(".jar") || lower.endsWith(".zip"))
269 return new JarClassPath(pathname);
270
271 int len = pathname.length();
272 if (len > 2 && pathname.charAt(len - 1) == '*'
273 && (pathname.charAt(len - 2) == '/'
274 || pathname.charAt(len - 2) == File.separatorChar)) {
275 String dir = pathname.substring(0, len - 2);
276 return new JarDirClassPath(dir);
277 }
278
279 return new DirClassPath(pathname);
280 }
281
282
283
284
285 void writeClassfile(String classname, OutputStream out)
286 throws NotFoundException, IOException, CannotCompileException
287 {
288 InputStream fin = openClassfile(classname);
289 if (fin == null)
290 throw new NotFoundException(classname);
291
292 try {
293 copyStream(fin, out);
294 }
295 finally {
296 fin.close();
297 }
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 InputStream openClassfile(String classname)
328 throws NotFoundException
329 {
330 ClassPathList list = pathList;
331 InputStream ins = null;
332 NotFoundException error = null;
333 while (list != null) {
334 try {
335 ins = list.path.openClassfile(classname);
336 }
337 catch (NotFoundException e) {
338 if (error == null)
339 error = e;
340 }
341
342 if (ins == null)
343 list = list.next;
344 else
345 return ins;
346 }
347
348 if (error != null)
349 throw error;
350 else
351 return null;
352 }
353
354
355
356
357
358
359
360
361
362 public URL find(String classname) {
363 ClassPathList list = pathList;
364 URL url = null;
365 while (list != null) {
366 url = list.path.find(classname);
367 if (url == null)
368 list = list.next;
369 else
370 return url;
371 }
372
373 return null;
374 }
375
376
377
378
379
380
381 public static byte[] readStream(InputStream fin) throws IOException {
382 byte[][] bufs = new byte[8][];
383 int bufsize = 4096;
384
385 for (int i = 0; i < 8; ++i) {
386 bufs[i] = new byte[bufsize];
387 int size = 0;
388 int len = 0;
389 do {
390 len = fin.read(bufs[i], size, bufsize - size);
391 if (len >= 0)
392 size += len;
393 else {
394 byte[] result = new byte[bufsize - 4096 + size];
395 int s = 0;
396 for (int j = 0; j < i; ++j) {
397 System.arraycopy(bufs[j], 0, result, s, s + 4096);
398 s = s + s + 4096;
399 }
400
401 System.arraycopy(bufs[i], 0, result, s, size);
402 return result;
403 }
404 } while (size < bufsize);
405 bufsize *= 2;
406 }
407
408 throw new IOException("too much data");
409 }
410
411
412
413
414
415
416 public static void copyStream(InputStream fin, OutputStream fout)
417 throws IOException
418 {
419 int bufsize = 4096;
420 byte[] buf = null;
421 for (int i = 0; i < 64; ++i) {
422 if (i < 8) {
423 bufsize *= 2;
424 buf = new byte[bufsize];
425 }
426 int size = 0;
427 int len = 0;
428 do {
429 len = fin.read(buf, size, bufsize - size);
430 if (len >= 0)
431 size += len;
432 else {
433 fout.write(buf, 0, size);
434 return;
435 }
436 } while (size < bufsize);
437 fout.write(buf);
438 }
439
440 throw new IOException("too much data");
441 }
442 }